!------------------------------------------------------------------------------
! TJU/Department of Mechanics, Fluid Mechanics, Code START
!------------------------------------------------------------------------------
!
!  File: /media/psf/Home/Fortran/START/src/module_cfgio_adapter.f90
!> @file
!> @breif cfgio代码适配器文件.
!  DESCRIPTION:
!>
!------------------------------------------------------------------------------

!------------------------------------------------------------------------------
! TJU/Department of Mechanics, Fluid Mechanics, Code START
!------------------------------------------------------------------------------
!
!  module: cfgio_adapter
!> @breif cfgio库的适配器模块.
!  DESCRIPTION:
!>
!!
!  REVISION HISTORY:
!  2017-08-01 - Initial Version
!  2018-09-14 - BiGlobal version
!  TODO_yyyy-mm-dd - TODO_describe_appropriate_changes - TODO_name
!> @author
!> Liu Jianxin
!> @date 2017-08-01

!------------------------------------------------------------------------------
module mod_cfgio_adapter

    use cfgio_mod
    use mod_parameter
    use mod_dis_wavenum
    use penf, only: R_P
    use stringifor
    implicit none

    public :: cfg_loader, prefix
    public :: wavenum_init, gridfile, flowfile, Curvaturefile
    public :: bctype
    public :: Istart
    public :: Iend
    public :: Iloc
    public :: kindSolver
    private

    type(string) :: gridfile   !<网格文件名
    type(string) :: flowfile   !<流场文件名
    type(String) :: Curvaturefile     !<曲率文件名
    type(string) :: prefix            !<文件名前缀
    integer :: bctype(5, 2)             !<边界条件类型
    type(dis_wavenum_type), allocatable :: wavenum_init(:) !<初始波数

    type(cfg_t), save :: cfg                            !<cfg类
    integer, parameter :: kd = kind('default')
    integer :: Istart         !< 流向计算域开始位置点序号
    integer :: Iend  !< 流向计算域结束位置点序号
    integer :: Iloc !< 当前流向位置
    integer :: kindSolver !< 求解器类型

    contains

    !> 从配置文件读取信息
    !! @param[in] cfgfn 配置文件文件名
    subroutine cfg_loader(cfgfn)

        implicit none
        character(kind=kd, len=*), intent(in) :: cfgfn

        cfg=parse_cfg(trim(cfgfn))
        call cfg_general(cfg)
        call cfg_domain(cfg)
        call cfg_filename(cfg)
        call cfg_freestream(cfg)
        call cfg_solver(cfg)
        call cfg_disturbances(cfg)
        call cfg_generic_bc(cfg)
        call cfg%write()
      !  write(*, *)

    end subroutine cfg_loader

    !> 通用信息提取函数
    !> @param[in] cfg cfg类
    !> @return 返回配置文件general字段相关信息
    subroutine cfg_general(cfg)

        implicit none
        type(cfg_t) :: cfg
        character(kind=kd, len=256) :: StringT

        if(cfg%has_key("general", "Title")) then
          call cfg%get("general", "Title", StringT)
        else
            StringT='Problem'
        end if

    end subroutine cfg_general

    !> 计算域信息提取函数
    !> @param[in] cfg cfg类
    !> @return 返回配置文件domain字段相关信息
    subroutine cfg_domain(cfg)

        implicit none
        type(cfg_t) :: cfg

        if(cfg%has_key("Domain", "Istart")) then
          call cfg%get("Domain", "Istart", istart)
        else
            istart=-1
        end if
        if(cfg%has_key("Domain", "ILoc")) then
          call cfg%get("Domain", "ILoc", iloc)
        else
            iloc=1
        end if

        if(cfg%has_key("Domain", "Iend")) then
          call cfg%get("Domain", "Iend", iend)
        else
            iend=-1
        end if

    end subroutine cfg_domain

    !> 文件信息提取函数
    !> @param[in] cfg cfg类
    !> @return 返回配置文件filnames字段相关信息
    subroutine cfg_filename(cfg)

        implicit none
        type(cfg_t) :: cfg
        character(kind=kd, len=256) :: grid
        character(kind=kd, len=256) :: flow
        character(kind=kd, len=256) :: Curvature
        character(kind=kd, len=256) :: Dir
        character(kind=kd, len=256) :: stringPrefix

        if(cfg%has_key("filenames", "Dir")) then
          call cfg%get("filenames", "Dir", dir)
        else
          Dir="./"
        endif
        call cfg%get("filenames", "Grid", grid)
        call cfg%get("filenames", "Flow", flow)
        call cfg%get("filenames", "Curvature", Curvature)
        if(cfg%has_key("filenames", "Output prefix") )then
          call cfg%get("filenames", "Output prefix", stringPrefix)
      prefix=trim(stringPrefix)
        else
          stringPrefix='UnNameCase'
        end if

        gridfile=trim(dir)//trim(grid)
        flowfile=trim(dir)//trim(flow)
        if(trim(Curvature)/='null')then
            Curvaturefile=trim(dir)//trim(Curvature)
        else
            Curvaturefile='null'
        end if

    end subroutine cfg_filename

    !> 来流信息提取函数
    !> @param[in] cfg cfg类
    !> @return 返回配置文件freestream字段相关信息
    subroutine cfg_freestream(cfg)

        implicit none
        type(cfg_t) :: cfg

        call cfg%get("Freestream", "Ma", Ma)
        call cfg%get("Freestream", "Re", Re)
        call cfg%get("Freestream", "Te", Te)

    end subroutine cfg_freestream

    !> 求解器信息提取函数
    !> @param[in] cfg cfg类
    !> @return 返回配置文件Solver字段相关信息
    subroutine cfg_solver(cfg)

        implicit none
        type(cfg_t) :: cfg
        character(kind=kd, len=256) :: solver
        integer, parameter :: BiGlobal=1

        if(cfg%has_key("Solver", "Type")) then
            call cfg%get("Solver", "Type", solver)
        elseif(cfg%has_key("Solver", "type")) then
            call cfg%get("Solver", "type", solver)
        else
            write(*, *) 'no solver set and LPSE is adopted!'
            solver='BiGlobal'
        endif

        select case (trim(solver))
        case ('BiGlobal', 'biglobal', 'Bi-Global', 'bi-global')
                kindsolver=BiGlobal
            case default
                write(*,*) "The solver type is wrong, and BiGlobal is used."
                kindsolver=BiGlobal
         end select

    end subroutine cfg_solver

    !> 扰动信息提取函数
    !> @param[in] cfg cfg类
    !> @return 返回配置文件Disturbances字段相关信息
    subroutine cfg_disturbances(cfg)

        implicit none
        type(cfg_t) :: cfg
        real(R_P) :: ome_in
        real(R_P), allocatable :: alf_in(:)
        complex(R_P) :: alf, ome
        integer :: DisNum, i
        character(3) :: chai
        character(kind=kd, len=256) :: optn
        integer :: npar

        call cfg%get("Disturbances", "Disturbances Number", DisNum)

        allocate(wavenum_init(DisNum))
        i=1
        write(chai, "(I3.3)")i
        optn="Disturbances_"//trim(chai)
        npar=2
        call cfg%get(trim(optn), "alpha", alf_in, npar)
        call cfg%get(trim(optn), "omega", ome_in)

        alf=alf_in(1)+CPLI*alf_in(2)
        ome=ome_in

        call wavenum_init(i)%Set(alf, ome)
        print*, '['//trim(optn)//']'
        print*, 'omega=', wavenum_init(i)%Omega
        print*, 'alpha=', wavenum_init(i)%Alpha

        print*, 'Disturbances are done.'

        !write(*, *)

    end subroutine cfg_disturbances

    !> 边界条件信息提取函数
    !> @param[in] cfg cfg类
    !> @return 返回配置文件Boundary Conditions字段相关信息
   subroutine cfg_generic_bc(cfg)

        implicit none
        type(cfg_t) :: cfg

        call cfg_bc_wall(cfg)
        call cfg_bc_freestream(cfg)

    end subroutine cfg_generic_bc

    !> 壁面边界条件提取函数
    !> @param[in] cfg cfg类
    !> @return 返回配置文件Boundary Conditions字段Wall相关信息
    subroutine cfg_bc_wall(cfg)

        implicit none
        type(cfg_t) :: cfg

        character(kind=kd, len=256) :: bc_type

        if(cfg%has_key("Boundary Conditions", "Wall_Vel")) then
          call cfg%get("Boundary Conditions", "Wall_Vel", bc_type)
          select case (trim(bc_type))
              case ('no_slip')
                bctype(2:4, 1)=(/2000, 3000, 4000/)
              case default
                stop "Please input correct Wall_Vel boundary condition."
          end select
        else
          bctype(2:4, 1)=(/2000, 3000, 4000/)
        endif

        if(cfg%has_key("Boundary Conditions", "Wall_T")) then
          call cfg%get("Boundary Conditions", "Wall_T", bc_type)
          select case (trim(bc_type))
              case ('adiabatic')
                bctype(5, 1)=5001
              case ('isothermal')
                bctype(5, 1)=5000
              case default
                  stop "Please input correct Wall_T boundary condition."
          end select
        else
          bctype(5, 1)=5000
        endif

        bctype(1, 1)=1004

    end subroutine cfg_bc_wall

    !> 远场边界条件信息提取函数
    !> @param[in] cfg cfg类
    !> @return 返回配置文件Boundary Conditions字段Freestream相关信息
    subroutine cfg_bc_freestream(cfg)

        implicit none
        type(cfg_t) :: cfg

        character(kind=kd, len=256) :: bc_type

        if(cfg%has_key("Boundary Conditions", "Freestream"))then
          call cfg%get("Boundary Conditions", "Freestream", bc_type)
          select case (trim(bc_type))
              case ('Dirichlet')
                bctype(1:5, 2)=(/1004, 2000, 3000, 4000, 5000/)
              case default
                stop "Please input correct Freestream boundary condition."
          end select
        else
          bctype(1:5, 2)=(/1004, 2000, 3000, 4000, 5000/)
        endif

    end subroutine cfg_bc_freestream

end module mod_cfgio_adapter
